#!/usr/bin/env python

import wx
import os

from server import *
from database import *
import wx.gizmos   as  gizmos
import wx.lib.agw.hypertreelist as HTL
import utils.singleton
from display.menu import *
from utils.commandmanager import CommandManager
from event.mouseevent import MouseEvent
from types import StringType
from conf import Conf
import media
import platform
import utils
        
#----------------------------------------------------------------------
# There are better ways to do IDs, but this demo requires that the window
# IDs be in a specific range. There are better ways to do that, too, but
# this will do for purposes of this demo.

ID_Menu_New         = 5004
ID_Menu_Exit        = 5005

ID_WINDOW_TOP       = 5000
ID_WINDOW_LEFT1     = 5001
ID_WINDOW_LEFT2     = 5002
ID_WINDOW_BOTTOM    = 5003

#----------------------------------------------------------------------
class Window(wx.Frame):
    def __init__(self, parent=None, title="Server"):
        wx.Frame.__init__(
            self, parent, -1, title, size=(500,600),
            style = wx.DEFAULT_FRAME_STYLE
            )
        media.init()
        
        
        self.panel=wx.Panel(self)
        #TreePannel(self)
        
        CommandManager().listener("exit",self.OnExit)
        self.CreateStatusBar()
        self.createMenu()
        self.createToolBar()
        self.crateLog()
        box = wx.BoxSizer(wx.VERTICAL)
        self.sizer=box
        self.panel.SetSizer(box)
        box.Add(TreePannel(self.panel), 1, wx.EXPAND)
        box.Add(self.log, 0, wx.EXPAND)
        box.Fit(self.panel)
        self.panel.Fit()
        self.Bind(wx.EVT_CLOSE,self.OnExit)
        #self.Bind(wx.EVT_PAINT, self.OnPaint)
        #self.Bind(wx.EVT_SIZE, self.OnSize)
    
    def OnSize(self, evt):
        self.Refresh()
        self.panel.Refresh()
        self.panel.Fit()
        self.sizer.Fit(self.panel)
        
    def crateLog(self):
        self.log = wx.TextCtrl(self.panel, -1, "", size=(200, 100), style=wx.TE_MULTILINE)
        
    def createMenu(self):
        self._menu=MainMenu(self)
        self._menu.quickMenu("F&ile","|Exit","Exit").setCommand("exit")
        self._menu.quickMenu("View","HTTP Server").setCommand("exit")
        self._menu.quickMenu("View","Database").setCommand("exit")
        self.SetMenuBar(self._menu)
        self._menu.build()

    def createToolBar(self):
        flags=( wx.TB_HORIZONTAL
            | wx.NO_BORDER
            | wx.TB_FLAT 
            )
        tb = self.CreateToolBar( flags )
        
        wx.ART_TOOLBAR
        tsize = (24,24)
        run_bmp =  wx.ArtProvider.GetBitmap(wx.ART_GO_FORWARD, wx.ART_TOOLBAR, tsize)
        stop_bmp =  wx.ArtProvider.GetBitmap(wx.ART_GO_BACK, wx.ART_TOOLBAR, tsize)

        tb.SetToolBitmapSize(tsize)

        tb.AddLabelTool(10, "Run",run_bmp, shortHelp="Run", longHelp="")
        tb.AddLabelTool(11, "Stop",stop_bmp, shortHelp="Stop", longHelp="")
        self.Bind(wx.EVT_TOOL, self.onRunClick, id=10)
        self.Bind(wx.EVT_TOOL, self.onStopClick, id=11)
        tb.Realize() 

    def onRunClick(self,e):
        Servers().start()
        
    def onStopClick(self,e):
        Servers().stop()
        

    def OnExit(self,e=None):
        try:
            Servers().stop()
        except:
            print "stop error"
        Conf().save()
        self.Unbind(wx.EVT_CLOSE,self)
        self.Destroy()


class TreePannel(gizmos.TreeListCtrl):
    def __init__(self,parent):
        gizmos.TreeListCtrl.__init__(self,parent, -1, style = wx.TR_ROW_LINES | wx.TR_HIDE_ROOT | wx.TR_TWIST_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT )
        #HTL.HyperTreeList.__init__(self,parent, -1,style=wx.SUNKEN_BORDER,
        #         agwStyle=wx.TR_HAS_BUTTONS | wx.TR_HAS_VARIABLE_ROW_HEIGHT)
        #self.SetAGWWindowStyleFlag(wx.TR_TWIST_BUTTONS)
        self.tree =self
        self.documentRoot=None
        self.mainServer=None

        self.tree.SetImageList(media.MediaLib())
        
        self.createTree()
        self.tree.DeleteChildren(self.root)
        self.addServer()
        self.addDatabase()

        
        CommandManager().listener("documentroot",self.onSetDocumentRoot)
        CommandManager().listener("renamefolder",self.onRename)
        CommandManager().listener("config",self.onChangeConfig)
        CommandManager().listener("option",self.onChangeOption)
        CommandManager().listener("start",self.onStart)
        CommandManager().listener("stop",self.onStop)
        CommandManager().listener("open",self.onOpen)
        CommandManager().listener("explore",self.onShowInExplorer)
        
        self.tree.Expand(Servers().getServerList()[0].node)
        self.tree.DragAcceptFiles(True)
        self.tree.Bind(wx.EVT_DROP_FILES, self.onDropFile)
        self.tree.Bind(wx.EVT_CONTEXT_MENU, self.onContextMenu)
        self.tree.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.onContextMenu)
        self.tree.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.onEndEdit)
        self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.onSelChanged)
        
    def createTree(self):
            
        self.tree.AddColumn("Main")
        self.tree.AddColumn("Status")
        self.tree.AddColumn("Value")
        
        self.tree.SetColumnWidth(0, 145)
        self.tree.SetColumnWidth(1, 45)
        self.tree.SetColumnWidth(2, 288)
        self.tree.SetMainColumn(0) # the one with the tree in it...
        #self.tree.SetColumnWidth(0, 16)
        self.root = self.tree.AddRoot("The Root Item")
        #wx.ART_EXECUTABLE_FILE
    
    
    
    def onSelChanged(self,e):
        pass
        

    def createFolderMenu(self,folder):
        menu=Menu(self.Parent)
        
        menu.quickMenu("Set DocumentRoot").setCommand("documentroot",folder)
        menu.quickMenu("|Shortcut")
        menu.quickMenu("Open").setCommand("open",folder)
        menu.quickMenu("Explore").setCommand("explore",folder)#addEventListener(MouseEvent.MOUSE_CLICK,self.onSetDocumentRoot)
        menu.quickMenu("|file")
        menu.quickMenu("Rename").setCommand("renamefolder",folder)## addEventListener(MouseEvent.MOUSE_CLICK,self.onRename)
        menu.build()
        return menu
        
    def createServerSubMenu(self,server):
        menu=Menu(self.Parent);
        menu.quickMenu("Start").setCommand("start",server)
        menu.quickMenu("Stop").setCommand("stop",server)
        menu.quickMenu("|config")
        menu.quickMenu("Config")
        if server.getOption("showOptions"):
            menu.quickMenu("[x]Show Infos").setCommand("option",server,"showOptions",False)
        else:
            menu.quickMenu("[]Show Infos").setCommand("option",server,"showOptions",True)
        #menu.quickMenu("Port")
        menu.quickMenu("|prorp")
        menu.quickMenu("Properties")
        
        
        list=server.getServerConf().getConfigsAvailable()
        for conf in list:
            if(conf==server.getServerConf().getDefaultConfig()):
                menu.quickMenu("Config","[x]"+conf).setCommand("config",server,conf)
            else:
                menu.quickMenu("Config","[]"+conf).setCommand("config",server,conf)
                
        menu.build()
        return menu
        
    def onChangeConfig(self,server,conf):
        print("onChangeConfig",conf)
        server=self.getServer(server)
        server.getServerConf().setDefaultConfig(conf)
    
    def onChangeOption(self,server,name,value):
        server=self.getServer(server)
        server.setOption(name,value)
        self.refreshServer(server)
        
    def onStart(self,server):
        server=self.getServer(server)
        server.start()
        self.refreshServer(server)
        
            
        
    def onStop(self,server):
        server=self.getServer(server)
        server.stop()
        self.refreshServer(server)
        
    def createDatabaseSubMenu(self,database):
        menu=Menu(self.Parent);
        menu.quickMenu("Start").setCommand("start",database)
        menu.quickMenu("Stop").setCommand("stop",database)
        menu.quickMenu("|prorp")
        menu.quickMenu("Properties")
        menu.build()
        return menu
        

    def onEndEdit(self,e):
        server=self.getServer(e.GetItem())
        server.removePath(self._old)
        server.addPath(e.GetLabel(),self.tree.GetItemText(e.GetItem(), 2))
        
    def onRename(self,folder):
        name=self.tree.GetItemText(folder, 2)
        server=self.getServer(folder)
        if server==None:
            return
        self._old=name
        #server.removePath(name)
        self.tree.EditLabel(folder)
        
    def onOpen(self,folder):
        if platform.system()=="Windows":
            utils.execCmd2(["explorer","http://127.0.1/"+self.tree.GetItemText(folder, 0)])
    
    def onShowInExplorer(self,folder):
        if platform.system()=="Windows":
            utils.execCmd2(["explorer",self.tree.GetItemText(folder, 2)])
    
    def onSetDocumentRoot(self,folder):
        self.setDocumentRoot(folder)
    
        
    def onContextMenu(self,e):
        #item, flags, col = self.tree.HitTest(e.GetPosition())
        selectedItem=e.GetItem()
        data=self.tree.GetPyData(selectedItem)
        if(isinstance(data,Server)):
            self.Parent.PopupMenu(self.createServerSubMenu(data))
        elif(isinstance(data,Database)):
            self.Parent.PopupMenu(self.createDatabaseSubMenu(data))
        else:
            self.Parent.PopupMenu(self.createFolderMenu(selectedItem))
        #self.folderMenu.Destroy()
     
    def getServer(self,item):
        if(isinstance(item,Server)):
            return item
        if(type(item)==str):
            return Servers().getServerByName(item)
        else:
            server=self.tree.GetPyData(item)
            while isinstance(server,Server)==False:
                item=self.tree.GetItemParent(item)
                if not item:
                    return None#server=list[len(list)-1]
                    break;
                server=self.tree.GetPyData(item)
            return server

    def onDropFile(self,e):
        item, flags, col = self.tree.HitTest(e.GetPosition())
        list=Servers().getServerList()
        server=None
        if item:
            server=self.getServer(item)
        if server==None:
            server=list[len(list)-1]

        #server.setDocumentRoot(e.GetFiles()[0])
        server.addPath(os.path.basename(e.GetFiles()[0]),e.GetFiles()[0])
        self.addFolder(server,e.GetFiles()[0])
        self.tree.Expand(server.node)

    def addDatabase(self):
        
        for database in Databases().getDatabaseList():
            child = self.tree.AppendItem(self.root, database.name)
            database.node=child
            self.tree.SetItemText(child, "Stop", 1)
            self.tree.SetItemText(child, os.path.abspath(database.path), 2)
            self.tree.SetItemImage(child, media.DATABASE_NETWORK)
            self.tree.SetPyData(child,database)


    def refreshServer(self,server):
        self.tree.DeleteChildren(server.node)
        if(server.started):
            self.tree.SetItemImage(server.node, media.SERVER_NETWORK)
            self.tree.SetItemText(server.node, "Start", 1)
        else:
            self.tree.SetItemImage(server.node, media.SERVER_NETWORK)
            self.tree.SetItemText(server.node, "Stop", 1)
        self.tree.SetItemText(server.node, os.path.abspath(server.path), 2)
        
        self.tree.SetPyData(server.node,server)
        list=server.getPaths()
        
        if server.getOption("showOptions"):
            self.showOption(server)
            
        for path in list:
            self.addFolder(server,path,list[path])
        
        if Servers().getCurrentServer()==server:
            if self.mainServer:
                self.tree.SetItemBold(self.mainServer,False)
            self.tree.SetItemBold(server.node,True)
            self.mainServer=server.node
    
    
    def addServer(self):
        for server in Servers().getServerList():
            child = self.tree.AppendItem(self.root, server.name)
            server.node=child
            self.refreshServer(server)
            
            #if server==Servers().getCurrentServer():
    
    
    def showOption(self,server):
        child = self.tree.AppendItem(server.node, "Options")
        
        self.tree.SetItemText(child, "-", 1)
        self.tree.SetItemText(child, "-", 2)
        self.tree.SetItemImage(child, media.SERVER_PROPERTY)
        self.addOption(child,"80","Port")
        node=self.addOption(child,"Modules","")
        self.addOption(node,"PHP","")
        #self.tree.SetPyData(child,none)
        
    def addOption(self,node,name,infos="",type=None,options=None):
        child = self.tree.AppendItem(node, name)
        
        self.tree.SetItemText(child, "-", 1)
        self.tree.SetItemText(child, infos, 2)
        self.tree.SetItemImage(child,  media.HAMMER)
        return child
            
    def addFolder(self,server,path="www",name=None):
        path=os.path.abspath(path)
        if not name:
            name=os.path.basename(path)
        child = self.tree.AppendItem(server.node, name)
        
        self.tree.SetItemText(child, "-", 1)
        self.tree.SetItemText(child, path, 2)
        self.tree.SetItemImage(child, media.FOLDER_NETWORK)
        self.tree.SetPyData(child,os.path.basename(path))
        path=path.replace("\\","/")
        if server.getDocumentRoot()==path:
            self.setDocumentRoot(child,server)
            
    
       
    def setDocumentRoot(self,item,server=None):
        if not server:
            server=self.getServer(item)
        server.setDocumentRoot(self.tree.GetItemText(item, 2))
        if self.documentRoot:
            self.tree.SetItemBold(self.documentRoot,False)
        self.tree.SetItemBold(item,True)
        self.documentRoot=item


if __name__ == '__main__':
    app = wx.App()
    win=Window()
    win.Show()
    app.MainLoop()

